//
// Created by fairy on 2025/5/13.
//
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
// 原始版本：
// 连续两次调用 fork()，导致父进程和第一个子进程（child1）都会创建子进程。最终生成4个进程：
// 1，原始父进程
// 2，父进程创建的 child1
// 3，父进程创建的 child2
// 4，child1 进程创建的 child2（额外产生的冗余子进程）

// 改进版本：
// 通过将第二个 fork() 嵌套在父进程的逻辑中，确保只有父进程会创建child2。最终生成3个进程：
// 1，原始父进程
// 2，父进程创建的 child1
// 3，父进程创建的 child2
int main(void)
{
    /*创建两个子进程*/
    const pid_t child1 = fork();
    /*子进程 1 的出错处理*/
    if (child1 == -1)
    {
        printf("Child1 fork error\n");
        exit(1);
    } else if (child1 == 0) /*在子进程 1 中调用 execlp() 函数*/
    {
        printf("In child1: execute 'ls -l'\n");
        if (execlp("ls", "ls", "-l", NULL) < 0)
        {
            printf("Child1 execlp error\n");
        }
    } else /*在父进程中再创建进程 2，然后等待两个子进程的退出*/
    {
        const pid_t child2 = fork();
        if (child2 == -1) /*子进程 2 的出错处理*/
        {
            printf("Child2 fork error\n");
            exit(1);
        } else if (child2 == 0) /*在子进程 2 中使其暂停 5s*/
        {
            printf("In child2: sleep for 5 seconds and then exit\n");
            sleep(5);
            exit(0);
        }

        printf("In father process:\n");

        pid_t child = waitpid(child1, NULL, 0); /* 阻塞式等待 */
        if (child == child1)
        {
            printf("Get child1 exit code\n");
        } else
        {
            printf("Error occured!\n");
        }

        do
        {
            child = waitpid(child2, NULL, WNOHANG); /* 非阻塞式等待 */
            if (child == 0)
            {
                printf("The child2 process has not exited!\n");
                sleep(1);
            }
        } while (child == 0);

        if (child == child2)
        {
            printf("Get child2 exit code\n");
        } else
        {
            printf("Error occured!\n");
        }
    }
    exit(0);
}
